package com.hup.utils.commons.exception.parser;

import com.hup.utils.commons.exception.AppExceptionHandler;
import com.hup.utils.commons.exception.ErrInfo;
import com.hup.utils.commons.exception.ErrParserRegister;
import com.hup.utils.commons.exception.ExceptionMsgParser;
import com.hup.utils.commons.exception.TraceHandler;

import java.io.FileNotFoundException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 * 一般的jdk异常
 *
 * @author hugan
 * @date 2019/8/24
 */
public class JdkErrParsers implements ErrParserRegister {

    @Override
    public List<ExceptionMsgParser> getParsers() {
        ArrayList<ExceptionMsgParser> list = new ArrayList<>();
        list.add(new OutOfMemory());
        list.add(new Null());
        list.add(new FileNotFound());
        list.add(new IndexOut());
        list.add(new Invocation());
        list.add(new InInitializerError());
        list.add(new StackOverflow());
        return list;
    }

    private static class OutOfMemory implements ExceptionMsgParser<OutOfMemoryError> {
        @Override
        public String getMsg(OutOfMemoryError e) {
            return e.getMessage();
        }
    }

    private static class Null implements ExceptionMsgParser<NullPointerException> {
        @Override
        public String getMsg(NullPointerException e) {
            return "空指针异常";
        }
    }

    private static class FileNotFound implements ExceptionMsgParser<FileNotFoundException> {
        @Override
        public String getMsg(FileNotFoundException e) {
            /*
            情况:
            1. 只有文件名
            2. 文件名 (系统找不到指定的文件。)
             */
            String message = e.getMessage();
            if (message != null) {
                int indexOf = message.indexOf("(系统找不到");
                if (indexOf != -1) {
                    message = message.substring(0, indexOf);
                }
            }
            return "找不到文件:" + message;
        }
    }

    private static class IndexOut implements ExceptionMsgParser<IndexOutOfBoundsException> {
        @Override
        public String getMsg(IndexOutOfBoundsException e) {
            if (e instanceof ArrayIndexOutOfBoundsException) {
                //只有一个数字
                return "索引越界,index=" + e.getMessage();
            }
            //Index: 3, Size: 0
            return "索引越界," + e.getMessage();
        }
    }

    private static class Invocation implements ExceptionMsgParser<InvocationTargetException> {
        @Override
        public String getMsg(InvocationTargetException e) {
            Throwable cause = e.getCause();
            if (cause != null) {
                //e.getMessage()是null
                return "反射调用异常," + cause.getMessage();
            }
            return "反射调用异常," + e.getMessage();
        }

        @Override
        public String getTrace(InvocationTargetException e) {
            return TraceHandler.TRACE_HANDLER.getTrace(e)
                    + TraceHandler.TRACE_HANDLER.getTrace(e.getCause());
        }
    }

    private static class InInitializerError implements ExceptionMsgParser<ExceptionInInitializerError> {
        @Override
        public String getMsg(ExceptionInInitializerError e) {
            return null;
        }

        @Override
        public ErrInfo getInfo(String msgHead, ExceptionInInitializerError e) {
            ErrInfo res;
            Throwable cause = e.getCause();
            if (cause != null) {
                res = AppExceptionHandler.handleNoLog("初始化错误,", cause);
                res.setTrace(TraceHandler.TRACE_HANDLER.getTrace(cause));
            } else {
                res = new ErrInfo();
                res.setMsg(msgHead, e.getMessage());
                res.setTrace(TraceHandler.TRACE_HANDLER.getTrace(e));
            }
            return res;
        }
    }

    private static class StackOverflow implements ExceptionMsgParser<StackOverflowError> {

        @Override
        public String getMsg(StackOverflowError e) {
            String message = e.getMessage();
            if (message != null) return message;
            return "出现死循环调用";
        }

        @Override
        public String getTrace(StackOverflowError e) {
            StringBuilder sb = new StringBuilder();
            sb.append("\n").append(e.getClass());
            StackTraceElement[] st = e.getStackTrace();
            for (int i = 0; i < st.length; i++) {
                sb.append("\n  \tat ").append(st[i]);
                if (i >= TraceHandler.TRACE_HANDLER.getMaxPrintCount() - 1) break;
            }
            return sb.toString();
        }
    }

}
